home *** CD-ROM | disk | FTP | other *** search
/ Aminet 16 / Aminet 16 (1996)(GTI - Schatztruhe)[!][Dec 1996].iso / Aminet / misc / emu / QDOS2.lha / QLsource / ROMsrc / PAR / PAR_asm
Text File  |  1994-07-27  |  12KB  |  523 lines

  1.     SECTION    PAR
  2.  
  3.     INCLUDE    '/INC/QDOS_inc'
  4.     INCLUDE    '/INC/AMIGA_inc'
  5.     INCLUDE    '/INC/AMIGQDOS_inc'
  6.  
  7. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  8. ; PAR1_asm - parallel device driver
  9. ;      - last modified 27/07/94
  10.  
  11. ; These are all the necessary parallel port related sources,
  12. ; required to implement a QDOS parallel device on the Amiga
  13. ; computer.
  14.  
  15. ; Amiga-QDOS sources by Rainer Kowallik
  16. ;  ...latest changes by Mark J Swift
  17.  
  18. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  19. ;  Channel definition block
  20.  
  21. PAR_TXQL EQU    81        ; Length of transmit buffer
  22.                 ; (odd!)
  23. PAR_DBGQL EQU    2048
  24.  
  25. PAR_PROT EQU    24        ; EOL Protocol, -ve RAW
  26.                 ; 0 CR/LF, 1 CR, 2 LF
  27. PAR_EOF    EQU    26        ; EOF (CLOSE) protocol
  28.                 ; -ve none, 0 FormFeed
  29. PAR_TXD    EQU    28        ; last transmitted character
  30. PAR_FLGS EQU    30        ; Bit 0    0 = busy
  31.                 ;    1 = ready
  32. PAR_TXQ    EQU    32        ; Transmit queue header
  33. PAR_END    EQU    PAR_TXQ+Q_QUEUE+PAR_TXQL+1 ; total memory
  34.  
  35. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  36. ;  ROM header
  37.  
  38. BASE:
  39.     dc.l    $4AFB0001    ; ROM recognition code
  40.     dc.w    0
  41.     dc.w    ROM_START-BASE
  42.     dc.b    0,36,'Amiga-QDOS PAR device driver v1.07 ',$A
  43.  
  44. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  45. ;  start of ROM code
  46.  
  47. ROM_START:
  48.     movem.l    d0-d2/a0-a3,-(a7)
  49.  
  50. ; --------------------------------------------------------------
  51. ;  allocate memory for parallel device variables
  52.  
  53.     move.l    #PV_LEN,d1
  54.     moveq    #MT.ALCHP,d0
  55.     moveq    #0,d2
  56.     trap    #1
  57.  
  58.     tst.l    d0
  59.     bne    ROM_EXIT
  60.  
  61. ; --------------------------------------------------------------
  62. ;  address of PAR variables
  63.  
  64.     move.l    a0,AV.PARV
  65.     move.l    a0,a3
  66.  
  67. ; --------------------------------------------------------------
  68. ;  enter supervisor mode and disable interrupts
  69.  
  70.     trap    #0
  71.  
  72.     ori.w    #$0700,sr    ; disable interrupts
  73.  
  74. ; --------------------------------------------------------------
  75. ;  link a custom routine into level 7 interrupt server
  76.  
  77.     lea    AV.LVL7link,a1
  78.     lea    PV.LVL7link(a3),a2
  79.  
  80.     move.l    (a1),(a2)
  81.     move.l    a2,(a1)
  82.  
  83.     lea    MY_LVL7(pc),a1
  84.     move.l    a1,$04(a2)
  85.  
  86. ; --------------------------------------------------------------
  87. ;  routines necessary for device driver
  88.  
  89.     lea    PAR_IO(pc),a2    ; Input/Output routine
  90.     move.l    a2,SV_AIO(a3)
  91.  
  92.     lea    PAR_OPEN(pc),a2    ; OPEN routine
  93.     move.l    a2,SV_AOPEN(a3)
  94.  
  95.     lea    PAR_CLOSe(pc),a2    ; CLOSE routine
  96.     move.l    a2,SV_ACLOS(a3)
  97.  
  98. ; --------------------------------------------------------------
  99. ;  routines necessary for IO.SERIO. (used by PAR I/O routine)
  100.  
  101.     lea    ERR_BP(pc),a2    ; test for pending input
  102.     move.l    a2,PV.PEND(a3)    ; (not provided)
  103.  
  104.     lea    ERR_BP(pc),a2    ; fetch byte
  105.     move.l    a2,PV.FBYTE(a3)    ; (not provided)
  106.  
  107.     lea    PAR_SBYT(pc),a2    ; send byte
  108.     move.l    a2,PV.SBYTE(a3)
  109.  
  110.     move.w    #$4E75,PV.RTS(A3) ; RTS instruction at $34
  111.  
  112. ; --------------------------------------------------------------
  113. ;  set up hardware
  114.  
  115.     bsr.s    INIT_HW
  116.  
  117. ; --------------------------------------------------------------
  118. ;  link in device driver
  119.  
  120.     lea    SV_LIO(a3),a0    ; link address
  121.     moveq    #MT.LIOD,d0    ; link in IO device driver
  122.     trap    #1
  123.  
  124. ; -------------------------------------------------------------
  125. ; link in external interrupt to act on port free
  126.  
  127.     lea    XINT_SERv(pc),a2    ; address of routine
  128.     move.l    a2,SV_AXINT(a3)
  129.     lea    SV_LXINT(a3),a0
  130.     moveq    #MT.LXINT,d0
  131.     trap    #1
  132.  
  133. ; -------------------------------------------------------------
  134. ; link in poll interrupt to re-enable parallel send
  135.  
  136.     lea    POLL_SERv(pc),a2    ; address of routine
  137.     move.l    a2,SV_APOLL(a3)
  138.     lea    SV_LPOLL(a3),a0
  139.     moveq    #MT.LPOLL,d0
  140.     trap    #1
  141.  
  142. ; --------------------------------------------------------------
  143. ;  enable interrupts and re-enter user mode
  144.  
  145.     andi.w    #$D8FF,sr
  146.  
  147. ; --------------------------------------------------------------
  148. ROM_EXIT:
  149.     movem.l    (a7)+,d0-d2/a0-a3
  150.  
  151.     rts
  152.  
  153. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  154. ;  set up hardware
  155.  
  156. INIT_HW:
  157.     movem.l    d7/a3,-(a7)
  158.  
  159.     move.l    AV.PARV,a3    ; address of PAR variables
  160.  
  161.     move.b    CIAA_ICR,d7    ; read & clear CIA-A ICR
  162.     or.b    AV.CIAA_ICR,d7
  163.     bclr    #4,d7        ; clear FLAG bit
  164.     move.b    d7,AV.CIAA_ICR    ; store for another program
  165.  
  166.     move.w    #%0000000000001000,INTREQ ; clear and enable
  167.     move.w    #%1000000000001000,INTENA ; CIA-A interrupts
  168.  
  169.     move.b    #%10010000,CIAA_ICR ; enable FLAG interrupt
  170.  
  171.     ori.b    #%00010000,AV.CIAA_MSK ; take note
  172.  
  173.     MOVE.B    #$FF,CIAA_DDRB    ; set DDRB to all output
  174.  
  175.     move.l    PV.PARTQ(a3),d7    ; address of transmit Q
  176.     beq.s    INIT_HWX     ; exit if Q doesn't exist
  177.  
  178.     move.l    d7,a3
  179.     bset    #0,1+PAR_FLGS-PAR_TXQ(a3) ; port ready
  180.  
  181. INIT_HWX:
  182.     movem.l    (a7)+,d7/a3
  183.     rts
  184.  
  185. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  186. ;  poll interrupt server for parallel port.
  187. ;  restarts interrupts by sending a byte.
  188.  
  189. POLL_SERv:
  190.     bsr    PAR_SEND     ; if port ready, send byte
  191.  
  192. POLL_X:
  193.     rts
  194.  
  195. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  196. ;  external interrupt server
  197.  
  198. XINT_SERv:
  199.     movem.l    d7/a0,-(a7)
  200.  
  201.     move.w    INTENAR,d7    ; read interrupt enable reg
  202.     btst    #3,d7        ; branch if ints not on
  203.     beq    XINT_OTHer
  204.  
  205.     move.w    INTREQR,d7    ; read interrupt request reg
  206.     btst    #3,d7        ; branch if from CIA-A or
  207.     bne    CIAA_SERv    ; expansion ports
  208.  
  209. ; --------------------------------------------------------------
  210. ;  otherwise let another external interrupt server handle it
  211.  
  212. XINT_OTHer:
  213.     movem.l    (a7)+,d7/a0
  214.     rts
  215.  
  216. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  217. ;  Interrupt from CIA-A or expansion port
  218.  
  219. CIAA_SERv:
  220.     move.b    CIAA_ICR,d7    ; read CIA-A ICR
  221.     or.b    AV.CIAA_ICR,d7
  222.     move.b    d7,AV.CIAA_ICR    ; store for another program
  223.  
  224.     bclr    #4,d7        ; port ready? (FLAG bit=1)
  225.     beq    XINT_OTHer    ; no
  226.  
  227. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  228. ;  External interrupt server for acting on par port ready
  229. ;  (CIAA FLAG bit=1).
  230.  
  231. PAR_RDY:
  232.     move.b    d7,AV.CIAA_ICR
  233.  
  234.     and.b    AV.CIAA_MSK,d7    ; don't clear INTREQ if
  235.     bne.s    PAR_RDY0     ; other CIAA ints occured
  236.  
  237.     move.w    #%0000000000001000,INTREQ ; clear interrupts
  238.  
  239. ; -------------------------------------------------------------
  240. PAR_RDY0:
  241.     move.l    AV.PARV,a0    ; address of PAR variables
  242.  
  243.     move.l    PV.PARTQ(a0),d7    ; address of transmit Q
  244.     beq.s    XINT_EXIt    ; exit if Q doesn't exist
  245.  
  246.     move.l    d7,a0
  247.     bset    #0,1+PAR_FLGS-PAR_TXQ(a0) ; port ready
  248.  
  249.     bsr    PAR_SEND
  250.  
  251. ; -------------------------------------------------------------
  252. XINT_EXIt:
  253.     bra    XINT_OTHer
  254.  
  255. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  256. ;  write next byte from queue to parallel port
  257.  
  258. PAR_SEND:
  259.     movem.l    d1/d7/a2-a4,-(a7)
  260.  
  261.     moveq    #ERR.NC,d0    ; assume no can do
  262.  
  263.     move.l    AV.PARV,a3    ; address of PAR variables
  264.  
  265.     move.l    PV.PARTQ(a3),d1    ; address of transmit Q
  266.     beq    PAR_S_X        ; exit if Q doesn't exist
  267.  
  268.     move.l    d1,a2
  269.     btst    #0,1+PAR_FLGS-PAR_TXQ(a2) ; port ready?
  270.     beq.s    PAR_S_X
  271.  
  272.     btst    #0,CIAB_PRA    ; printer busy?
  273.     bne.s    PAR_S_X
  274.  
  275.     btst    #1,CIAB_PRA    ; paper out?
  276.     bne.s    PAR_S_X
  277.  
  278.     btst    #2,CIAB_PRA    ; printer select?
  279.     beq.s    PAR_S_X
  280.  
  281.     moveq    #0,d1
  282.     move.w    IO.QOUT,a4
  283.     jsr    (a4)        ; get byte d1 from queue a2
  284.     tst.l    d0
  285.     bne.s    PAR_S_X        ; exit if error
  286.  
  287.     bclr    #0,1+PAR_FLGS-PAR_TXQ(a2) ; port busy
  288.  
  289.     move.b    CIAA_ICR,d7    ; read CIA-A ICR
  290.     or.b    AV.CIAA_ICR,d7
  291.     bclr    #4,d7        ; clear FLAG bit
  292.     move.b    d7,AV.CIAA_ICR    ; store for another program
  293.     move.w    #%0000000000001000,INTREQ ; clear interrupts
  294.  
  295.     move.b    d1,CIAA_PRB    ; write data to par port
  296.  
  297. PAR_S_X:
  298.     movem.l    (a7)+,d1/d7/a2-a4
  299.     rts
  300.  
  301. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  302. ; Here we start with the parallel interface. Although it would
  303. ; be possible to read from the hardware, I first write this
  304. ; driver for output only.
  305. ; I'm following the example from the advanced user guide to
  306. ; avoid any problems, and get the whole thing to work as quickly
  307. ; as possible!
  308. ;                    Rainer Kowallik
  309.  
  310. PAR_OPEN:
  311.     suba.w    #4,a7        ; room for 5 words on
  312.     movea.l    a7,a3        ; stack.
  313.  
  314.     move.w    IO.NAME,a4    ; decode device name
  315.     JSR    (A4)
  316.  
  317.     BRA.S    PAR_O_X        ; not found
  318.     BRA.S    PAR_O_X        ; bad device name
  319.     BRA.S    PAR_O_CHK    ; OK, name was PAR_
  320.  
  321.     dc.w    3        ; length of device name
  322.     dc.b    'PAR',0        ; definition is PAR
  323.     dc.w    2        ; 2 parameters
  324.  
  325.     dc.w    4        ; char value, 4 options
  326.     dc.b    'RNCL'        ; eol protocol
  327.  
  328.     dc.w    1        ; char value, 2 options
  329.     dc.b    'F',0        ; eof protocol
  330.  
  331. ; --------------------------------------------------------------
  332. PAR_O_X:
  333.     adda.w    #4,a7
  334.     ANDI.W    #$F8FF,SR
  335.     RTS
  336.  
  337. ; --------------------------------------------------------------
  338. PAR_O_CHK:
  339.     move.l    AV.PARV,a3    ; address of PAR variables
  340.  
  341.     move.l    PV.PARTQ(a3),d0    ; address set?
  342.     beq.s    PAR_O_CHK1    ; no queue, no chan def blk
  343.  
  344.     movea.l    d0,a0
  345.     suba.w    #PAR_TXQ,a0    ; addrs of old chan def blk
  346.     bclr    #7,PAR_TXQ(a0)    ; output queue empty?
  347.     bne.s    PAR_O_CHK2    ; yes, so continue
  348.     bra.s    PAR_O_IU     ; no, so exit with error
  349.  
  350. PAR_O_CHK1:
  351.     move.w    #(PAR_END),d1    ; allocate chan def block
  352.     move.w    MM.ALCHP,a4    ; for first time
  353.     JSR    (A4)
  354.     bne.s    PAR_O_X        ; exit if error occured
  355.  
  356.     moveq    #PAR_TXQL,d1    ; length of transmit queue
  357.     lea    PAR_TXQ(a0),a2    ; address of transmit queue
  358.     move.w    IO.QSET,a4    ; set up queue (not used
  359.     jsr    (a4)        ; before
  360.  
  361.     move.l    AV.PARV,a3    ; address of PAR variables
  362.     move.l    a2,PV.PARTQ(a3)
  363.  
  364. PAR_O_CHK2:
  365.     move.w    (a7),PAR_PROT(a0) ; store handshake, protocol
  366.     move.w    2(a7),PAR_EOF(a0) ; store EOF protocol
  367.  
  368.     subq.w    #2,PAR_PROT(a0)    ; -ve raw : 0 CR/LF : 1 CR : 2 LF
  369.     subq.w    #1,PAR_EOF(a0)    ; -ve none : 0 FF : CTRL-Z
  370.  
  371.     bset    #0,1+PAR_FLGS(a0) ; set 'port ready' flag
  372.  
  373. ; --------------------------------------------------------------
  374. PAR_O_OK:
  375.     moveq    #ERR.OK,d0    ; signal "no error"
  376.     bra    PAR_O_X
  377.  
  378. ; --------------------------------------------------------------
  379. PAR_O_NF:
  380.     moveq    #ERR.NF,d0    ; not found
  381.     bra    PAR_O_X
  382.  
  383. ; --------------------------------------------------------------
  384. PAR_O_IU:
  385.     moveq    #ERR.IU,d0    ; in use
  386.     bra    PAR_O_X
  387.  
  388. ; --------------------------------------------------------------
  389. PAR_CLOSe:
  390.     tst.b    1+PAR_EOF(a0)
  391.     blt.s    PAR_C2        ; cont if no eof protocol
  392.  
  393.     move.w    #12,d1        ; send Form Feed
  394.  
  395. PAR_CLUP:
  396.     bsr    PAR_SBOK
  397.     cmp.w    #ERR.NC,d0
  398.     beq.s    PAR_CLUP
  399.  
  400. PAR_C2:
  401.     lea    PAR_TXQ(a0),a2
  402.     move.w    IO.QEOF,a4    ; put EOF marker in queue
  403.     jsr    (a4)
  404.  
  405.     moveq    #ERR.OK,d0    ; signal "no errors"
  406.     rts
  407.  
  408. ; --------------------------------------------------------------
  409. PAR_IO:
  410.     CMP.B    #$7,D0        ; trap file operations
  411.     BHI    ERR_BP
  412.  
  413.     pea    PV.PEND(a3)    ; pretend call just before
  414.     move.w    IO.SERIO,a4
  415.     JMP    (A4)
  416.  
  417. ; --------------------------------------------------------------
  418. PAR_SBYT:
  419.     lea    PAR_TXQ(a0),a2
  420.  
  421.     move.l    d1,d3
  422.     move.w    IO.QTEST,a4
  423.     jsr    (a4)
  424.     move.l    d3,d1
  425.  
  426.     cmpi.w    #ERR.EF,d0
  427.     beq.s    PAR_SB4
  428.  
  429.     moveq    #ERR.OK,d0
  430.  
  431.     cmpi.w    #$6,d2        ; reasonable space in Q?
  432.     bge.s    PAR_SB5
  433.  
  434.     moveq    #ERR.NC,d0
  435.  
  436. PAR_SB4:
  437.     rts
  438.  
  439. PAR_SB5:
  440.     move.b    1+PAR_TXD(a0),d3    ; remember old TX code
  441.     move.b    d1,1+PAR_TXD(a0)    ; save new TX code
  442.  
  443.     tst.b    1+PAR_PROT(a0)
  444.     blt.s    PAR_SBOK     ; branch if no eol protocol
  445.  
  446.     cmpi.b    #$0A,d1        ; Line Feed?
  447.     beq.s    PAR_SB1
  448.  
  449.     cmpi.b    #$0D,d1        ; Carriage Return?
  450.     bne.s    PAR_SBOK     ; branch if neither
  451.  
  452. PAR_SB1:
  453.     cmpi.b    #$0A,d3        ; Line Feed?
  454.     beq.s    PAR_SB2
  455.  
  456.     cmpi.b    #$0D,d3        ; Carriage Return?
  457.     bne.s    PAR_SB3
  458.  
  459. PAR_SB2:
  460.     cmp.b    d1,d3
  461.     beq.s    PAR_SB3
  462.  
  463.     move.b    #$FF,1+PAR_TXD(a0) ; ignore LF in CR/LF couple
  464.     moveq    #ERR.OK,d0
  465.     rts
  466.  
  467. PAR_SB3:
  468.     tst.b    1+PAR_PROT(a0)
  469.     beq.s    PAR_SB6        ; branch if CR/LF protocol
  470.  
  471.     cmp.b    #2,1+PAR_PROT(a0)
  472.     beq.s    PAR_SB7        ; branch if LF
  473.  
  474.     moveq    #$0D,d1        ; else use CR
  475.     bra.s    PAR_SBOK
  476.  
  477. PAR_SB6:
  478.     moveq    #$0D,d1
  479.     bsr    PAR_SBOK
  480.  
  481. PAR_SB7:
  482.     moveq    #$0A,d1
  483.  
  484. PAR_SBOK:
  485.     lea    PAR_TXQ(a0),a2
  486.  
  487.     move.w    IO.QIN,a4    ; put byte d1 into queue a2
  488.     jsr    (a4)
  489.     rts
  490.  
  491. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  492. ERR_OK:
  493.     moveq    #ERR.OK,d0    ; "no error"
  494.     rts
  495.  
  496. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  497. ERR_NC:
  498.     moveq    #ERR.NC,d0    ; "not complete"
  499.     rts
  500.  
  501. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  502. ERR_BP:
  503.     moveq    #ERR.BP,d0    ; "bad parameter"
  504.     rts
  505.  
  506. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  507. ;  Custom LVL7 routine to initialise hardware
  508.  
  509. MY_LVL7:
  510.     bsr    INIT_HW
  511.  
  512.     subq.l    #4,a7
  513.     movem.l    a3,-(a7)
  514.     move.l    AV.PARV,a3
  515.     move.l    PV.LVL7link(a3),a3
  516.     move.l    4(a3),4(a7)    ; address of next routine
  517.     movem.l    (a7)+,a3
  518.  
  519.     rts
  520.  
  521. ; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  522.     END
  523.